import json
from datetime import datetime

from django.http import QueryDict, JsonResponse, HttpResponse
from django.utils.deprecation import MiddlewareMixin

from gis.admin.const import ACTION
from gis.common import track_logging
from gis.common.django_ext.views import PaginationResponse
from gis.common.exceptions import BizException
from gis.common.json import JsonEncoder
from gis.common.utils import get_request_ip, get_request_user_agent, shorten_user_agent

_LOGGER = track_logging.getLogger(__name__)


class ApiMiddleware(MiddlewareMixin):
    def process_request(self, request):
        request.DATA = QueryDict("")
        if request.method == "GET":
            body = request.META["QUERY_STRING"]
        else:
            body = request.body.decode()
        request.DATA = QueryDict(body)

    def process_exception(self, request, exception):
        if isinstance(exception, BizException):
            response = dict(
                status=exception.error_code.code,
                msg=exception.detail_message,
                timestamp=datetime.now(),
            )
        else:
            response = dict(status=-1, msg="内部错误，请联系管理员", timestamp=datetime.now())
            _LOGGER.exception(
                "catched error %s in %s, uid:%s",
                exception.__class__.__name__,
                request.path,
                request.user_id if hasattr(request, "user_id") else None,
            )
        return JsonResponse(response, encoder=JsonEncoder, status=500)

    def process_response(self, request, response):
        if isinstance(response, (dict, list, PaginationResponse)):
            wrap_data = dict(status=0, msg="OK", timestamp=datetime.now())
            if isinstance(response, PaginationResponse):
                response = dict(
                    total=response.total, items=response.items, **response.kwargs
                )
            wrap_data["data"] = response
            return JsonResponse(wrap_data, encoder=JsonEncoder)
        elif isinstance(response, str):
            return HttpResponse(response)
        elif response is None:
            return HttpResponse("")
        else:
            return response


class OperationLogMiddleware(MiddlewareMixin):
    def process_request(self, request):
        pass

    def process_exception(self, request, exception):
        pass

    def process_response(self, request, response):
        try:
            if isinstance(response, dict):
                handle_oper_record(request, response)
        except Exception:
            _LOGGER.info("OperationLogMiddleware  exception", exc_info=True)
        return response


def handle_oper_record(req, resp):
    if req.method not in ACTION:
        return
    try:
        resource_id = resp.get("id")
        action = ACTION[req.method]
        content = req.body.decode() if req.body else ""
        resource = req.permission_code if hasattr(req, "permission_code") else None
        operator = req.user_id if hasattr(req, "user_id") else None
        ip = get_request_ip(req)
        user_agent = shorten_user_agent(get_request_user_agent(req))
        if req.path == "/api/admin/login/":  # 登录时去除密码明文
            resource = "admin_login"
            operator = resp["id"]
            temp = json.loads(content)
            temp.pop("password")
            content = json.dumps(temp)
        elif resource == "admin_user_add":  # 新增用户时，去除密码明文
            temp = json.loads(content)
            temp.pop("password")
            content = json.dumps(temp)

        from gis.admin.services import admin_service

        admin_service.insert_record(
            resource, resource_id, action, content, operator, ip, user_agent
        )
    except Exception as e:
        _LOGGER.exception("insert record exception {}".format(e))
